// SPDX-License-Identifier: GPL-2.0+
/*
 * Timer for X1830
 *
 * Copyright (c) 2013 Imagination Technologies
 * Author: Paul Burton <paul.burton@imgtec.com>
 */

#include <config.h>
#include <common.h>
#include <div64.h>
#include <asm/io.h>
#include <asm/mipsregs.h>
#include <asm/arch/x1830.h>

#define OST_OSTCCR				0x00
#define OST_OSTESR				0x34
#define OST_OSTECR				0x38
#define OST_OSTCR				0x08
#define OST_OST2CNTL			0x20
#define OST_OSTCNT2HBUF			0x24

#define OSTCCR_PRESCALE2_DIV16	(2 << 2)

#define OSTESR_OST2ENS			(1 << 1)

#define OSTECR_OST2ENC			(1 << 1)

#define OSTCR_OST2CLR			(1 << 1)

int timer_init(void)
{
	void __iomem *regs = (void __iomem *)OST_BASE;

	writel(OSTECR_OST2ENC, regs + OST_OSTECR);
	writel(OSTCR_OST2CLR, regs + OST_OSTCR);
	writel(OSTCCR_PRESCALE2_DIV16, regs + OST_OSTCCR);
	writel(OSTESR_OST2ENS, regs + OST_OSTESR);
	return 0;
}

static u64 get_timer64(void)
{
	void __iomem *regs = (void __iomem *)OST_BASE;
	u32 low = readl(regs + OST_OST2CNTL);
	u32 high = readl(regs + OST_OSTCNT2HBUF);

	return ((u64)high << 32) | low;
}

ulong get_timer(ulong base)
{
	return lldiv(get_timer64(), CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ) - base;
}

void __udelay(unsigned long usec)
{
	u32 tmo;
	u64 end;

	/* OST count increments at 1.5MHz */
	tmo = CONFIG_SYS_HZ_CLOCK / 1000;
	tmo *= usec;
	tmo /= 1000;

	end = get_timer64() + tmo;

	while (get_timer64() < end)
		;
}

unsigned long long get_ticks(void)
{
	return get_timer64();
}
